home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI MineSet 2.5
/
SGI MineSet 2.5.iso
/
dist
/
imgtools.idb
/
usr
/
sgitcl
/
lib
/
system.imgtclrc.z
/
system.imgtclrc
Wrap
Text File
|
1998-05-12
|
16KB
|
567 lines
#
# system.imgtclrc -- initialization for imgtcl module.
#
#
# Execute the autogenerated stuff and the manually generated stuff...
#
if {[info exists env(IMGTCL_VERBOSE)]} {
puts -nonewline stderr "dlopening imgtcl.so..."
}
dlopen libimgtcl.so init imgtcl_init
if {[info exists env(IMGTCL_VERBOSE)]} {
puts stderr "done."
}
# ---------------------------------------------------------------------------
# comment (not perfect; e.g. it evaluates bracketed expressions in comments
proc // {args} {}
proc XXX {args} {puts "XXX $args"}
// this sucks...
// switch {5} {
3 {puts "three"}
2 {puts "two"}
$five {puts "FIVE"}
default {puts "the default"}
}
# ----------------------------------------------------------------------------
# System constants...
# ----------------------------------------------------------------------------
# "const" is like "set" but it makes the variable read-only,
# and adds it to the list of consts.
proc const {name value} {
global $name
set $name $value
trace variable $name w attempted_write_to_const
global consts
lappend consts $name
}
proc attempted_write_to_const {name element operation} {
if {$element != ""} {
set name ${name}($element)
}
error "it's a constant, you dummy."
}
const NULL 0
# XXX umm... uhh... how to distinguish between NULL and an empty string?
const HZ 100
# XXX don't hard-code in here!
const 0 0; # for things like $[rImg.getResampType]
# ----------------------------------------------------------------------------
# IL Constants...
# ----------------------------------------------------------------------------
const FALSE 0
const TRUE 1
proc unimplemented {name} {
global ilOKAY
proc $name {args} "
puts {$name not implemented yet...}
return $ilOKAY
"
}
proc unimplemented_object {classname objname} {
global ilOKAY
proc $objname {methodname args} "
puts \"invoked object $objname's method $classname::\$methodname which is not implemented yet...\"
return $ilOKAY
"
}
proc unimplemented_class {classname} {
proc $classname {objname args} "
puts \"created object \$objname of class $classname which is not implemented yet...\"
unimplemented_object $classname \$objname
return \$objname
"
}
proc unimplemented_ptrclass {classname} {
proc $classname {objname args} "
return \$objname
"
}
# -----------------------------------------------------------------------------
# IL Stubs...
# -----------------------------------------------------------------------------
unimplemented_ptrclass ilView*
// XXX should put a trace on pointer variables to make sure they get the right type!
unimplemented_ptrclass ilImage*
unimplemented_ptrclass ilImage**
unimplemented_ptrclass ilFileImg*
unimplemented_ptrclass ilFileImg**
if {0} {
# hack to define and use a few structs... I'm not sure what we'll use
# eventually...
proc iflXYint {objname args} {
global $objname
set ${objname}(x) 0
set ${objname}(y) 0
}
proc iflXYSint {objname args} {
global $objname
set ${objname}(x) 0
set ${objname}(y) 0
}
proc iflXYSint_array {name init_list} {
upvar $name A
set n [llength $init_list]
for {set i 0} {$i < $n} {incr i} {
set A($i,x) [lindex [lindex $init_list $i] 0]
set A($i,y) [lindex [lindex $init_list $i] 1]
}
}
proc iflXYSfloat_array {name init_list} {
upvar $name A
for {set i 0} {$i < 3} {incr i} {
set A($i,x) [lindex [lindex init_list $i] 0]
set A($i,y) [lindex [lindex init_list $i] 1]
}
}
proc short {name} {
# do nothing
}
proc int {name} {
# do nothing
}
}
proc getdescription {name} {
global description
if {[info exists description($name)]} {
return $description($name)
} else {
return $name
}
}
// Support obj.method syntax...
// I have misgivings about this, since it is a performance drain every time
// any method command is executed.
// XXX idea: the first time foo.bar is executed, it could
// actually create a command called foo.bar;
// then subsequent calls wouldn't need to go through this "unknown" mechanism.
// But then these would need to be deleted when the object is deleted,
// which would be a bloody mess to keep track of...
rename unknown _unknown_pre_il
proc unknown {name args} {
#
# If $name is of the form obj.method, call $obj $method.
#
if {[scan $name {%[^.].%s} obj method] == 2} {
return [uplevel $obj $method $args]
}
#
# If $name is of the form ptr->method, call $$ptr $method.
#
if {[scan $name {%[^-]->%s} ptr method] == 2} {
return [uplevel [uplevel set $ptr] $method $args]
}
#
# If $name is of the form (classname*)addr, call $classname:: $addr.
#
if {[scan $name {(%[_a-zA-Z0-9]*)%s} classname addr] == 2} {
return [uplevel $classname:: $addr $args]
}
#
# If $name is of the form (struct_or_scalar_name {dims})addr,
# call $struct_or_scalarname:: $dims $addr
#
if {[scan $name {(%[_a-zA-Z0-9] {%[^\}]})%s} structname dims addr] == 3} {
return [va_uplevel _array_command $structname $dims $addr $args]
}
#
# Call the default "unknown".
# The following would do it:
# return [uplevel _unknown_pre_il $name $args]
# except that we want to discard the stack trace from this point down.
# So instead we catch the error (if there is one)
# and pass it up with an empty stack trace.
#
set code [catch {uplevel _unknown_pre_il $name $args} result]
return -code $code $result
}
# Wanted to call this "array", but tcl already has
# such a command...
proc new {type name {dims ""} {equals ""} {initlist ""}} {
global sizeof
if {! [regexp {^[_a-zA-Z]} $name]} {
# no name supplied-- shift args accordingly
set initlist $equals
set equals $dims
set dims $name
set name ""
}
if {$dims == ""} {
return -code 1 "dims not specified properly"
}
# XXX here, check whether a variable or procedure
# of this name exists, and if so, reject.
# (Then won't need the "write" trace below, only the "unset" trace.
if { [regexp {\*$} $type] } {
set sizeoftype $sizeof(void*)
} else {
set sizeoftype $sizeof($type)
}
if {$equals == "addr" && [string range $initlist 0 2] != "0x"} {
# memory is being passed to us, don't allocate any, just use it
set equals ""
set addr $initlist
set initlist ""
set ownMemory 0
} else {
set addr [malloc [expr $sizeoftype * [join $dims *]]]
if {! $addr} {
return -code 1 "malloc([expr $sizeoftype * [join $dims *]]) failed"
}
set ownMemory 1
}
set result "($type {$dims})$addr"
if {$addr != 0} {
if {$equals != "" || $initlist != ""} {
if {$equals != "=" || $initlist == ""} {
free $addr
return -code 1 "invalid initializer \"$equals $initlist\""
}
if {[catch {$result = $initlist} error_result] == 1} {
free $addr
return -code 1 $error_result
}
}
}
if {$name != ""} {
#
# Set the named variable to the string containing
# the address and indexing info...
# Note that this will trigger cleaning up of any
# previous value of the variable and command,
# so it must be done before we define the command.
#
uplevel [list set $name $result]
#
# Create a command called name...
# This doesn't accomplish much in the current implementation,
# but if the "new" command is rewritten in C,
# it could allocate a struct describing the array and strides
# and use this as the client data,
# so that they wouldn't need to be recalculated every dang
# time the array is derefed.
#
set hidden_name [_localproc_uniquename]
if {[info commands $name] != {}} {
rename $name $hidden_name
}
proc $name {args} "
va_call _array_command $type \{$dims\} $addr \$args
"
# set the trace on the variable to free the space and delete the command
# unless this was an "addr" style initialization in which case we don't
# own the memory
if ($ownMemory) {
uplevel [list trace variable $name wu \
"array_unset_or_reset_callback \"$result\" $hidden_name"]
}
}
return $result
}
#
# Calling a function and passing it the trailing varargs "args" arguments
# seems to be extremely awkward in tcl; here is a function that does it.
# Takes any number of arguments; the first one should be a command name, and
# the last one should be an "args" list that will get expanded
# and passed to the command along with the preceding arguments.
#
proc va_call {args} {
set nargs [llength $args]
set lastargs [lindex $args [expr $nargs - 1]]
set firstargs [lrange $args 0 [expr $nargs - 2]]
eval [concat $firstargs $lastargs]
}
proc va_uplevel {args} {
# Note, does not understand the "level" argument of uplevel
set nargs [llength $args]
set lastargs [lindex $args [expr $nargs - 1]]
set firstargs [lrange $args 0 [expr $nargs - 2]]
uplevel [concat $firstargs $lastargs]
}
#XXX
proc printvar {name} {
upvar $name value
puts "$name = \"$value\""
}
proc _array_command {type dims addr args} {
# Suppose A is "(iflSize {2 3})0x123456".
# Then "A 0" or "A {0} should return "(iflSize {3})0x12345".
# "A + 1" should return "(iflSize {1 3})0x12345a"
# "A 0 0" or "A {0 0}" should return "{512 512 1 3}"
# "A 0 0 x" or "A {0 0} x" should return "512"
# "A 0 0 x = 20" or "A {0 0} x = 20" should set A[0][0].x = 20
global sizeof
#printvar type
#printvar dims
#printvar addr
#printvar args
#
# Set inds equal to the concatenation of all the
# initial args that look like numbers or lists of numbers.
#
set inds ""
while {[regexp {^[0-9]} [set firstarg [lindex $args 0]]]} {
set inds [concat $inds $firstarg]
set args [lreplace $args 0 0]
}
#printvar inds
#printvar args
#puts ""
set ndims [llength $dims]
set ninds [llength $inds]
if {$ninds > $ndims} {
error "Too many indices $inds for ($type {$dims})$addr"
}
if { [regexp {\*$} $type] } {
set mangledtype "void_ptr_"
set sizeoftype $sizeof(void*)
} else {
set mangledtype $type
set sizeoftype $sizeof($type)
}
#
# Peel off a dimension and an index, until there are no more indices...
#
while {$ninds > 0} {
set dim0 [lindex $dims 0]
set ind0 [lindex $inds 0]
if {$ind0 < 0 || $ind0 >= $dim0} {
error "Index \"$ind0\" out of bounds \"$dim0\" for ($type {$dims})$addr"
}
set addr [expr $addr + $ind0 * $sizeoftype * [join $dims *] / $dim0]
set addr [format %#x $addr] ;# XXX possible performance drain here
set dims [lrange $dims 1 end]
set inds [lrange $inds 1 end]
incr ndims -1
incr ninds -1
}
if {$ndims > 0} {
if {$args == {}} {
# This is the syntax for returning the array as a list
set args "="
}
if {[lindex $args 0] == "="} {
switch [llength $args] {
1 {
#
# Return the entire C array as a list
#
set result {}
set dim0 [lindex $dims 0]
for {set i 0} {$i < $dim0} {incr i} {
lappend result [_array_command $type $dims $addr $i =]
}
return $result
}
2 {
#
# Set the C array from the explicit list given
#
set initlist [lindex $args 1]
set ninits [llength $initlist]
if {$ninits > [lindex $dims 0]} {
error "Initializer list $initlist too long for ($type {$dims})$addr"
}
for {set i 0} {$i < $ninits} {incr i} {
_array_command $type $dims $addr $i = [lindex $initlist $i]
}
return ""
}
default {
puts [llength $args]
error "Bad initializer \"$args\" for ($type {$dims})$addr"
}
}
} elseif {[lindex $args 0] == "+"} {
if {[llength $args] != 1} {
....
XXX
}
} else {
error "Unrecognized argument syntax \"$args\" for ($type {$dims})$addr"
}
}
# At this point, $ndims and $ninds are both 0
if {$args == "="} {
return [$mangledtype:: $addr]
} else {
return [va_call $mangledtype:: $addr $args]
}
}
proc array_unset_or_reset_callback {old_value hidden_name name element op} {
# XXX The following may be a performance drain...
global env
if {[info exists env(IMGTCL_UNSET_VERBOSE)]} {
puts stderr "In array unset cb, name=$name, elt=$element, op=$op, old value=$old_value"
}
free $old_value
rename $name ""
if {[info commands $hidden_name] != {}} {
rename $hidden_name $name
}
uplevel [list trace vdelete $name wu \
"array_unset_or_reset_callback \"$old_value\" $hidden_name"]
}
#
# "localproc" is like "proc" but it
# creates a procedure that is local to the current stack frame;
# i.e. it gets destroyed and the previous implementation (if any)
# is restored when the current stack frame is destroyed.
#
# This is complicated due to ugliness in the unset-trace implementation.
# For example, to implement a local procedure "foo",
# call
# localproc foo {...} {
# ...
# }
# How this is implemented:
# chooses a unique name like __localproc_uniquename_2983
# if there's already a function named foo,
# then rename it __localproc_uniquename_2983
# creates the function foo as specified
#
# set __localproc_uniquename_2983(foo) "arbitrary value"
# put a trace on __localproc_uniquename_2983(foo)
# so that when it is unset, we will
# restore the original procedure foo.
# (Note: The reason we encode the procedure name
# and its "hidden name" in the name of the variable
# rather than in the contents of the variable
# is that the contents of the variable
# are undefined while the unset-trace-callback
# is being executed (which seems silly to me,
# but that's the way it is)).
# set __localproc_hidden_name(foo) __localproc_uniquename_2983
# (Note: The reason we also set __localproc_hidden_name(foo)
# is so that we can implement a procedure "unlocalproc"
# which will restore the original foo;
# it needs to be able to look up the hidden name
# knowing only the name "foo", and it can't do this
# from only the variable __localproc_uniquename_2983(foo).
#
#
proc localproc {procname args body} {
if {[uplevel info exists __localproc_hidden_name($procname)]} {
error "localproc \"$procname\" already exists"
}
set hidden_name [_localproc_uniquename]
if {[info commands $procname] != {}} {
rename $procname $hidden_name
}
uplevel [list set __localproc_hidden_name($procname) $hidden_name]
uplevel [list trace variable __localproc_hidden_name($procname) wu \
"_localproc_unset_trace $procname $hidden_name"]
uplevel [list proc $procname $args $body]
}
proc unlocalproc {procname} {
# The unset-trace callback is what does the real work...
uplevel [list unset __localproc_hidden_name($procname)]
}
proc _localproc_unset_trace {procname hidden_name name elt op} {
rename $procname ""
if {[info commands $hidden_name] != {}} {
rename $hidden_name $procname
}
}
set __localproc_uniquename_i 0
proc _localproc_uniquename {} {
global __localproc_uniquename_i
return __localproc_uniquename_[incr __localproc_uniquename_i]
}
// {
# -----------------------------------------------------------------------------
# Experimenting with calling-with-named-args...
# The original way... (note that the y=0 default is useless)
proc foo {a b {c 0}} {}
proc bar {x {y 0} z args} {}
# Split into the "real" functions and the user-friendly "wrapper" functions...
proc _foo {a b {c 0}} {}
proc _bar {x {y 0} z args} {}
proc foo {args} {
set c 0
foreach
}
}
# Set prompt for interactive sessions...
# Do this last; if an error occurred before this point,
# the user will know something is wrong because the prompt is unfamiliar...
set tcl_prompt1 "puts -nonewline \"imgtcl> \""
set tcl_prompt2 "puts -nonewline \"> \""
return; # so return value will be "" and not the result of the previous command
}